package com.anpy.bill.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.SecretKey;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import org.apache.commons.codec.binary.Base64;

/**
 * @version V2.0
 * @Author: sgy
 * @Description:
 * @date 2018/4/10 16:31
 */
@Slf4j
public class JWTUtil {
    private static String stringKey = "7786df7fc3a34e26a61c034d5ec8245d";

    public static String createJWT(Map<String, String> data) throws ParseException {
        log.info("加密接口初始化参数开始！");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = new Date();
        Date endDate = new Date();
        if (data.get("startTime") != null && data.get("startTime").length() != 0) {
            startDate = simpleDateFormat.parse(data.get("startTime"));
        }
        if (data.get("endTime") != null && data.get("endTime").length() != 0) {
            endDate = simpleDateFormat.parse(data.get("endTime"));
        }
        long ttlMillis = endDate.getTime() - startDate.getTime();
        if (data.get("minutes") != null && data.get("minutes").length() != 0) {
            ttlMillis = Long.parseLong(data.get("minutes")) * 1000 * 60;
        }
        //判断时间长度大小
        ttlMillis = (endDate.getTime() - (new Date()).getTime() - ttlMillis) > 0L ? (endDate.getTime() - startDate.getTime()) : ttlMillis;
        String userId = data.get("userId") != null && !"".equals(data.get("userId")) ? data.get("userId") : null;
        String prjLable = data.get("prjLable") != null && !"".equals(data.get("prjLable")) ? data.get("prjLable") : "jxsd";
        //指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容封装好了。
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey key = generalKey();
        log.info("加密接口初始化参数结束！");
        Map<String, Object> claims = new HashMap<String, Object>();
        List<String> listCla = new ArrayList<String>(data.keySet());
        for (int i = 0; i < listCla.size(); i++) {
            claims.put(listCla.get(i), data.get(listCla.get(i)));
        }
        //下面就是在为payload添加各种标准声明和私有声明了
        String token = Jwts.builder()
                .setClaims(claims)
                .setId(prjLable)
                .setIssuedAt(now)
                .setIssuer(userId)
                .signWith(key, signatureAlgorithm)
                .compact();
        //如果过期时间不为0  则设置过期时间
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            token = Jwts.builder()
                    .setClaims(claims)
                    .setId(prjLable)
                    .setIssuedAt(now)
                    .setIssuer(userId)
                    .setExpiration(exp)
                    .signWith(key, signatureAlgorithm)
                    .compact();
        }
        return token;
    }

    /**
     * 解密jwt
     */
    public static Claims parseJWT(Map<String, String> data) {
        String jwt = data.get("token");
        SecretKey key = generalKey();
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }

    /**
     * 解密jwt
     *
     * @param jwt
     */
    public static Claims parseJWT(String jwt) {
        SecretKey key = generalKey();
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }

    /**
     * 由字符串生成加密key
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        // 确保密钥长度至少为256位（32字节）
        if (encodedKey.length < 32) {
            byte[] newKey = new byte[32];
            System.arraycopy(encodedKey, 0, newKey, 0, Math.min(encodedKey.length, 32));
            // 如果原始密钥不足32字节，用0填充
            for (int i = encodedKey.length; i < 32; i++) {
                newKey[i] = 0;
            }
            encodedKey = newKey;
        }
        return Keys.hmacShaKeyFor(encodedKey);
    }

}
